package com.youlu.campus.service.ca.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.ActivityInfo;
import com.youlu.campus.entity.CaGroupInfo;
import com.youlu.campus.entity.CaInfo;
import com.youlu.campus.entity.VO.req.CaGroupInfoQueryVO;
import com.youlu.campus.entity.VO.req.CopyCa;
import com.youlu.campus.entity.VO.req.CopyCaInfoReq;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.service.ca.CaGroupInfoService;
import com.youlu.campus.service.ca.CaInfoService;
import com.youlu.campus.service.cache.CacheCaGroupInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotBlank;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CaGroupInfoServiceImpl implements CaGroupInfoService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CacheCaGroupInfoService cacheCaGroupInfoService;

    @Lazy
    @Autowired
    private CaInfoService caInfoService;

    @Override
    public Page<CaGroupInfo> list(CaGroupInfoQueryVO req) {
        log.info(":>>> 开始获取证书分组列表:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || Objects.isNull(req.getPage()) || Objects.isNull(req.getPageSize())) {
            log.error(":>>> 参数错误:分页、页码为空");
            throw new BusinessException("参数错误:分页、页码为空");
        }
        Query query = new Query();
        if (StringUtils.isNotBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
        if (Objects.nonNull(req.getTaskBizType())) {
            query.addCriteria(Criteria.where("taskBizType").is(req.getTaskBizType()));
        }
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, CaGroupInfo.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<CaGroupInfo> infos = mongoTemplate.find(query.with(pageRequest), CaGroupInfo.class);
        for (CaGroupInfo caGroupInfo : infos) {
            Query query1 = new Query().addCriteria(Criteria.where("caGroupInfoId").is(caGroupInfo.getId()));
            Long num = mongoTemplate.count(query1, CaInfo.class);
            caGroupInfo.setSkuNum(num.intValue());
            if (StringUtils.isNotBlank(caGroupInfo.getActivityId())) {
                ActivityInfo activityInfo = this.mongoTemplate.findById(caGroupInfo.getActivityId(),
                        ActivityInfo.class);
                if (Objects.nonNull(activityInfo)) {
                    caGroupInfo.setActivityName(activityInfo.getName());
                }
            }
        }
        return PageableExecutionUtils.getPage(infos, pageRequest, () -> count);
    }

    @Override
    public boolean delete(String tenantId, String id) {
        log.info(":>>> 开始删除证书分组:{},{}", tenantId, id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 参数错误:ID不能为空");
            throw new BusinessException("参数错误:ID不能为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("deleted", true);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, CaGroupInfo.class);
        boolean re = updateResult.getModifiedCount() > 0 ? true : false;
        log.info(":>>>  删除证书分组:{} 结果:{}", id, re);
        Query queryCaInfo = new Query().addCriteria(Criteria.where("caGroupInfoId").is(id));
        update.set("deleted", true);
        mongoTemplate.updateMulti(queryCaInfo, update, CaInfo.class);
        return re;
    }

    @Override
    public boolean create(CaGroupInfo req) {
        log.info(":>>> 开始创建证书分组:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || Objects.isNull(req.getName()) || Objects.isNull(req.getActivityId()) || Objects.isNull(req.getTaskBizType())) {
            log.error(":>>> 活动ID和证书类型为空");
            throw new BusinessException("活动ID和证书类型为空");
        }
        Query query =
                new Query().addCriteria(Criteria.where("name").is(req.getName()).and("activityId").is(req.getActivityId()));
        boolean exist = mongoTemplate.exists(query, CaGroupInfo.class);
        if (exist) {
            log.error("证书系列:{} 已经存在", req.getName());
            throw new BusinessException("证书系列已经存在");
        }
        Query query1 = new Query().addCriteria(Criteria.where("id").is(req.getActivityId()));
        ActivityInfo activityInfo = mongoTemplate.findOne(query1, ActivityInfo.class);
        if (Objects.nonNull(activityInfo)) {
            req.setActivityName(activityInfo.getName());
        }
        req.setCreatedTime(new Date());
        req.setId(null);
        mongoTemplate.insert(req);
        return true;
    }

    @Override
    public boolean update(CaGroupInfo req) {
        log.info(":>>> 开始修改证书分组:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 参数错误:ID不能为空");
            throw new BusinessException("参数错误:ID不能为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getActivityId())) {
            update.set("activityId", req.getActivityId());
        }
        if (StringUtils.isNotBlank(req.getName())) {
            update.set("name", req.getName());
        }
        if (Objects.nonNull(req.getTaskBizType())) {
            update.set("taskBizType", req.getTaskBizType());
        }
        if (Objects.nonNull(req.getBuyMultiCA())) {
            update.set("buyMultiCA", req.getBuyMultiCA());
        }
        update.set("updatedTime", new Date());
        update.set("openCountDown", req.getOpenCountDown());
        update.set("countDownTips", req.getCountDownTips());
        update.set("footerMarketingClaim", req.getFooterMarketingClaim());
        update.set("connectCoupon", req.getConnectCoupon());
        update.set("sellingTitle", req.getSellingTitle());
        update.set("choicePriority", req.getChoicePriority());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, CaGroupInfo.class);
        cacheCaGroupInfoService.remove(req.getActivityId(), req.getTaskBizType());
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public CaGroupInfo findOne(String id) {
        log.info(":>>> 获取证书系列:{}", id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 证书系列 id为空");
            throw new BusinessException("证书系列 id为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, CaGroupInfo.class);
    }

    @Override
    public CaGroupInfo find(String activityId, TaskBizType taskBizType) {
        log.info(":>>> 开始获取证书分组:{},{}", activityId, taskBizType);
        Query query =
                new Query().addCriteria(Criteria.where("activityId").is(activityId).and("taskBizType").is(taskBizType));
        CaGroupInfo caGroupInfo = mongoTemplate.findOne(query, CaGroupInfo.class);
        log.info(":>>> 获取证书分组为:{}", JSON.toJSONString(caGroupInfo));
        return caGroupInfo;
    }

    @Override
    public void copyCaGroupInfo(String copyActivityId, String newActivityId) {
        log.info("【copy 活动】开始复制活动证书序列->{} copyActivityId", copyActivityId);
        Query query = new Query().addCriteria(Criteria.where("activityId").is(copyActivityId));
        List<CaGroupInfo> groupInfoList = this.mongoTemplate.find(query, CaGroupInfo.class);
        if (CollectionUtils.isEmpty(groupInfoList)) {
            log.error("【copy 活动】结束复制活动证书序列->{} 未查询到数据 copyActivityId", copyActivityId);
            return;
        }
        Date now = new Date();
        List<CaGroupInfo> targetCaGroupInfoList = groupInfoList.stream().peek(caGroupInfo -> {
            String oldCaGroupInfoId = caGroupInfo.getId();
            caGroupInfo.setId(ObjectId.get().toString());
            caGroupInfo.setCreatedTime(now);
            caGroupInfo.setUpdatedTime(now);
            caGroupInfo.setActivityId(newActivityId);
            CopyCaInfoReq copyCaInfoReq = new CopyCaInfoReq();
            copyCaInfoReq.setCopyActivityId(copyActivityId);
            copyCaInfoReq.setCopySourceCaGroupId(oldCaGroupInfoId);
            copyCaInfoReq.setTargetCaGroupId(caGroupInfo.getId());
            copyCaInfoReq.setTargetCopyActivityId(newActivityId);
            caInfoService.copyCaInfo(copyCaInfoReq);
        }).collect(Collectors.toList());
        this.mongoTemplate.insertAll(targetCaGroupInfoList);
        log.info("【copy 活动】结束复制活动证书序列->{} copyActivityId", copyActivityId);
    }

    @Override
    public void copyCa(CopyCa req) {
        String copyCurrentId = req.getCopyCurrentId();
        String targetCopyActivityId = req.getTargetCopyActivityId();
        String targetCaType = req.getTargetCaType();
        log.info("【copy 活动证书序例】start 复制活动证书序列copyCurrentId:{}|targetCopyActivityId:{}|targetCaType:{}", copyCurrentId,
                targetCopyActivityId, targetCaType);
        CaGroupInfo sourceCaGroupInfo = this.mongoTemplate.findById(copyCurrentId, CaGroupInfo.class);
        if(Objects.isNull(sourceCaGroupInfo)){
            log.error("【copy 活动证书序例】复制活动证书序列copyCurrentId:{}|targetCopyActivityId:{}|targetCaType:{} 未查询到相关证书",
                    copyCurrentId,
                    targetCopyActivityId, targetCaType);
            return;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(targetCopyActivityId));
        query.addCriteria(Criteria.where("taskBizType").is(targetCaType));
        boolean exists = this.mongoTemplate.exists(query, CaGroupInfo.class);
        if(exists){
            log.error(":>>> 复制证书的时已经存在:{},{}",targetCopyActivityId,targetCaType);
            throw new BusinessException("目标活动证书类型下已有证书，不能重复创建");
        }
        ActivityInfo targetActivityInfo = this.mongoTemplate.findById(targetCopyActivityId, ActivityInfo.class);
        if(Objects.isNull(targetActivityInfo)){
            return;
        }
        String id = new ObjectId().toString();
        Date now = new Date();
        CaGroupInfo targetCaGroupInfo = new CaGroupInfo();
        BeanUtils.copyProperties(sourceCaGroupInfo,targetCaGroupInfo);
        targetCaGroupInfo.setActivityId(targetCopyActivityId);
        targetCaGroupInfo.setTaskBizType(targetCaType);
        targetCaGroupInfo.setName(req.getTargetCaName());
        targetCaGroupInfo.setActivityName(targetActivityInfo.getName());
        targetCaGroupInfo.setId(id);
        targetCaGroupInfo.setCreatedTime(now);
        targetActivityInfo.setUpdatedTime(now);
        this.mongoTemplate.save(targetCaGroupInfo);
        query = new Query();
        query.addCriteria(Criteria.where("caGroupInfoId").is(sourceCaGroupInfo.getId()));
        List<CaInfo> caInfoList = this.mongoTemplate.find(query, CaInfo.class);
        if(CollectionUtils.isEmpty(caInfoList)){
            return;
        }
        List<CaInfo> targetCaInfoList = caInfoList.stream().peek(caInfo -> {
            caInfo.setId(null);
            caInfo.setCreatedTime(now);
            caInfo.setUpdatedTime(now);
            caInfo.setCaGroupInfoId(id);
            caInfo.setActivityId(targetCopyActivityId);
            caInfo.setGiftItems(null);
            caInfo.setMaterialConfigId("");
            caInfo.setMaterialConfigName("");
            caInfo.setItemMaterialList(null);
        }).collect(Collectors.toList());
        this.mongoTemplate.insertAll(targetCaInfoList);
        log.info("【copy 活动证书序例】end 复制活动证书序列copyCurrentId:{}|targetCopyActivityId:{}|targetCaType:{}", copyCurrentId,
                targetCopyActivityId, targetCaType);
    }

    @Override
    public List<CaGroupInfo> find(String activityId) {
        log.info(":>>> 开始获取证书分组:{}", activityId);
        Query query =
                new Query().addCriteria(Criteria.where("activityId").is(activityId));
        List<CaGroupInfo> caGroupInfos = mongoTemplate.find(query, CaGroupInfo.class);
        log.info(":>>> 获取证书分组为:{}", JSON.toJSONString(caGroupInfos));
        return caGroupInfos;
    }
}
